from flask import Flask, request, jsonify, make_response
from flask_cors import CORS
import json
import logging
import requests
import os
from dotenv import load_dotenv
import websocket
import ssl
import base64
import hmac
import hashlib
from datetime import datetime
from time import mktime
from urllib.parse import urlencode, urlparse
from wsgiref.handlers import format_date_time
import threading
import time

# 加载环境变量
load_dotenv()

app = Flask(__name__)
CORS(app)

# 设置Flask应用的JSON编码为UTF-8
app.config['JSON_AS_ASCII'] = False

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# 通义千问API配置
# 移除通义千问相关的导入和配置
# DASHSCOPE_API_KEY = os.getenv('DASHSCOPE_API_KEY', 'sk-your-api-key-here')
# DASHSCOPE_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1"

# 讯飞星火Spark Lite API配置
SPARK_LITE_APP_ID = os.getenv('SPARK_LITE_APP_ID', '')
SPARK_LITE_API_SECRET = os.getenv('SPARK_LITE_API_SECRET', '')
SPARK_LITE_API_KEY = os.getenv('SPARK_LITE_API_KEY', '')
SPARK_LITE_URL = os.getenv('SPARK_LITE_URL', 'wss://spark-api-open.xf-yun.com/v1/chat')
SPARK_LITE_HTTP_URL = os.getenv('SPARK_LITE_HTTP_URL', 'https://spark-api-open.xf-yun.com/v1/chat/completions')

class SparkLiteAPI:
    """讯飞星火Spark Lite API调用类"""
    
    def __init__(self, app_id, api_secret, api_key, gpt_url):
        self.app_id = app_id
        self.api_secret = api_secret
        self.api_key = api_key
        self.host = urlparse(gpt_url).netloc
        self.path = urlparse(gpt_url).path
        self.gpt_url = gpt_url
        self.result = ""
        self.error = None
        
    def create_url(self):
        """生成WebSocket连接URL"""
        # 生成RFC1123格式的时间戳
        now = datetime.now()
        date = format_date_time(mktime(now.timetuple()))
        
        # 拼接字符串 - 注意这里使用api_key而不是app_id
        signature_origin = "host: " + self.host + "\n"
        signature_origin += "date: " + date + "\n"
        signature_origin += "GET " + self.path + " HTTP/1.1"
        
        # 进行hmac-sha256进行加密 - 使用api_secret作为密钥
        signature_sha = hmac.new(self.api_secret.encode('utf-8'), 
                                signature_origin.encode('utf-8'),
                                digestmod=hashlib.sha256).digest()
        
        signature_sha_base64 = base64.b64encode(signature_sha).decode(encoding='utf-8')
        
        # 注意这里使用api_key而不是app_id
        authorization_origin = f'api_key="{self.api_key}", algorithm="hmac-sha256", headers="host date request-line", signature="{signature_sha_base64}"'
        
        authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')
        
        # 将请求的鉴权参数组合为字典
        v = {
            "authorization": authorization,
            "date": date,
            "host": self.host
        }
        # 拼接鉴权参数，生成url
        url = self.gpt_url + '?' + urlencode(v)
        return url
    
    def on_error(self, ws, error):
        """WebSocket错误处理"""
        logger.error(f"Spark Lite WebSocket error: {error}")
        self.error = str(error)
    
    def on_close(self, ws, close_status_code, close_msg):
        """WebSocket关闭处理"""
        logger.info("Spark Lite WebSocket connection closed")
    
    def on_open(self, ws):
        """WebSocket连接建立后发送请求"""
        def run(*args):
            data = {
                "header": {
                    "app_id": self.app_id,
                    "uid": "fd3f47e4-d"
                },
                "parameter": {
                    "chat": {
                        "domain": "lite",
                        "temperature": 0.7,
                        "max_tokens": 1024
                    }
                },
                "payload": {
                    "message": {
                        "text": self.messages
                    }
                }
            }
            ws.send(json.dumps(data))
        
        threading.Thread(target=run).start()
    
    def on_message(self, ws, message):
        """处理WebSocket消息"""
        try:
            data = json.loads(message)
            code = data['header']['code']
            
            if code != 0:
                logger.error(f"Spark Lite API error: {data['header']['message']}")
                self.error = data['header']['message']
                ws.close()
                return
            
            choices = data["payload"]["choices"]
            status = choices["status"]
            content = choices["text"][0]["content"]
            
            self.result += content
            
            if status == 2:  # 结束
                ws.close()
                
        except Exception as e:
            logger.error(f"Error processing Spark Lite message: {e}")
            self.error = str(e)
            ws.close()
    
    def call_api(self, messages):
        """调用Spark Lite API - 优先使用HTTP接口，失败时回退到WebSocket"""
        try:
            # 首先尝试HTTP接口
            logger.info("Attempting Spark Lite HTTP API call")
            return self.call_api_http(messages)
        except Exception as http_error:
            logger.warning(f"Spark Lite HTTP API failed: {http_error}, falling back to WebSocket")
            
            # HTTP失败时回退到WebSocket
            try:
                return self.call_api_websocket(messages)
            except Exception as ws_error:
                logger.error(f"Both HTTP and WebSocket failed. HTTP: {http_error}, WebSocket: {ws_error}")
                raise Exception(f"Spark Lite API call failed. HTTP: {http_error}, WebSocket: {ws_error}")
    
    def call_api_websocket(self, messages):
        """使用WebSocket接口调用Spark Lite API"""
        self.messages = messages
        self.result = ""
        self.error = None
        
        try:
            websocket.enableTrace(False)
            ws_url = self.create_url()
            ws = websocket.WebSocketApp(ws_url,
                                      on_message=self.on_message,
                                      on_error=self.on_error,
                                      on_close=self.on_close,
                                      on_open=self.on_open)
            
            ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
            
            if self.error:
                raise Exception(self.error)
                
            return self.result
            
        except Exception as e:
            logger.error(f"Spark Lite WebSocket API call failed: {e}")
            raise e
    
    def call_api_http(self, messages):
        """使用HTTP接口调用Spark Lite API"""
        try:
            # 检查是否有HTTP认证信息
            http_api_key = os.getenv('SPARK_LITE_HTTP_API_KEY')
            http_api_secret = os.getenv('SPARK_LITE_HTTP_API_SECRET')
            
            if http_api_key and http_api_secret:
                # 使用讯飞官方文档要求的APIPassword认证方式
                # APIPassword格式: api_key:api_secret
                api_password = f"{http_api_key}:{http_api_secret}"
                headers = {
                    'Content-Type': 'application/json',
                    'Authorization': f'Bearer {api_password}'
                }
            else:
                raise Exception("HTTP API credentials not configured")
            
            # 构建请求数据
            data = {
                "model": "lite",
                "messages": messages,
                "stream": False,
                "max_tokens": 1024,
                "temperature": 0.7
            }
            
            # 发送HTTP请求
            response = requests.post(
                SPARK_LITE_HTTP_URL,
                headers=headers,
                json=data,
                timeout=30
            )
            
            if response.status_code == 200:
                result = response.json()
                if 'choices' in result and len(result['choices']) > 0:
                    return result['choices'][0]['message']['content']
                else:
                    raise Exception("Invalid response format from Spark Lite HTTP API")
            else:
                raise Exception(f"HTTP request failed with status {response.status_code}: {response.text}")
                
        except Exception as e:
            logger.error(f"Spark Lite HTTP API call failed: {e}")
            raise e
    
    def _generate_http_auth_headers_with_credentials(self, api_key, api_secret):
        """使用指定的API Key和Secret生成HTTP接口的认证头"""
        # 生成RFC1123格式的时间戳
        now = datetime.now()
        date = format_date_time(mktime(now.timetuple()))
        
        # 解析HTTP URL
        parsed_url = urlparse(SPARK_LITE_HTTP_URL)
        host = parsed_url.netloc
        path = parsed_url.path
        
        # 构建签名原文 - 按照讯飞官方文档格式
        # 格式: host: $host\ndate: $date\n$request-line
        signature_origin = f"host: {host}\ndate: {date}\nPOST {path} HTTP/1.1"
        
        # 使用HMAC-SHA256算法签名
        signature_sha = hmac.new(
            api_secret.encode('utf-8'),
            signature_origin.encode('utf-8'),
            digestmod=hashlib.sha256
        ).digest()
        
        # Base64编码签名
        signature_sha_base64 = base64.b64encode(signature_sha).decode('utf-8')
        
        # 构建authorization_origin字符串
        authorization_origin = f'api_key="{api_key}", algorithm="hmac-sha256", headers="host date request-line", signature="{signature_sha_base64}"'
        
        # Base64编码authorization
        authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode('utf-8')
        
        # 返回请求头，必须包含Host字段以满足讯飞API的签名验证要求
        return {
            'Content-Type': 'application/json',
            'Host': host,
            'Date': date,
            'Authorization': authorization
        }
    
    def _generate_http_auth_headers(self):
        """生成HTTP接口的认证头"""
        # 生成RFC1123格式的时间戳
        now = datetime.now()
        date = format_date_time(mktime(now.timetuple()))
        
        # 解析HTTP URL
        parsed_url = urlparse(SPARK_LITE_HTTP_URL)
        host = parsed_url.netloc
        path = parsed_url.path
        
        # 构建签名原文 - 按照讯飞官方文档格式
        # 格式: host: $host\ndate: $date\n$request-line
        signature_origin = f"host: {host}\ndate: {date}\nPOST {path} HTTP/1.1"
        
        # 使用HMAC-SHA256算法签名
        signature_sha = hmac.new(
            self.api_secret.encode('utf-8'),
            signature_origin.encode('utf-8'),
            digestmod=hashlib.sha256
        ).digest()
        
        # Base64编码签名
        signature_sha_base64 = base64.b64encode(signature_sha).decode('utf-8')
        
        # 构建authorization_origin字符串
        authorization_origin = f'api_key="{self.api_key}", algorithm="hmac-sha256", headers="host date request-line", signature="{signature_sha_base64}"'
        
        # Base64编码authorization
        authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode('utf-8')
        
        # 返回请求头，必须包含Host字段以满足讯飞API的签名验证要求
        return {
            'Content-Type': 'application/json',
            'Host': host,
            'Date': date,
            'Authorization': authorization
        }

def call_spark_lite_api(prompt):
    """
    调用讯飞星火Spark Lite API进行智能分析
    """
    try:
        if not SPARK_LITE_APP_ID or not SPARK_LITE_API_SECRET or not SPARK_LITE_API_KEY:
            raise Exception("Spark Lite API credentials not configured")
        
        spark_api = SparkLiteAPI(SPARK_LITE_APP_ID, SPARK_LITE_API_SECRET, SPARK_LITE_API_KEY, SPARK_LITE_URL)
        
        messages = [
            {
                "role": "user",
                "content": prompt
            }
        ]
        
        result = spark_api.call_api(messages)
        logger.info("Spark Lite API call successful")
        return result
        
    except Exception as e:
        logger.error(f"Spark Lite API call failed: {e}")
        raise e

# 删除call_qwen_api函数
# def call_qwen_api(prompt, model="qwen-plus"):
#     """
#     调用通义千问API进行智能分析
#     """
#     # 函数内容已删除

def analyze_resume_with_ai(resume_text, industry=None):
    """
    使用讯飞星火Lite API分析简历
    """
    try:
        # 构建分析提示词
        industry_map = {
            'technology': '技术/IT行业',
            'finance': '金融行业',
            'education': '教育行业',
            'healthcare': '医疗健康行业',
            'manufacturing': '制造业',
            'retail': '零售行业',
            'consulting': '咨询行业',
            'media': '媒体行业',
            'real_estate': '房地产行业',
            'logistics': '物流行业',
            'government': '政府/公共部门',
            'other': '其他行业'
        }
        
        # 如果industry在预定义映射中，使用映射值；否则直接使用用户输入的行业名称
        if industry in industry_map:
            industry_name = industry_map[industry]
        else:
            # 直接使用用户输入的自定义行业名称
            industry_name = industry if industry else '技术/IT行业'
        
        prompt = f"""
请分析以下简历与{industry_name}的匹配情况，并提供详细的分析报告：

简历内容：
{resume_text}

目标行业：{industry_name}

请按照以下JSON格式返回分析结果：
{{
    "keywords": ["关键词1", "关键词2", "关键词3"],
    "strengths": "优势分析（150字以内）",
    "weaknesses": "待改进项（150字以内）", 
    "suggestions": "优化建议（150字以内）"
}}

分析要求：
1. 关键词：提取简历中与目标行业相关的技能、经验关键词（3-8个）
2. 优势分析：客观分析简历与目标行业的匹配优势
3. 待改进项：指出简历中不足或与目标行业不匹配的地方
4. 优化建议：提供具体的改进建议

请确保分析客观准确，特别注意简历专业背景与目标行业的匹配度。
"""

        # 直接使用Spark Lite API
        logger.info("使用Spark Lite API进行简历分析")
        try:
            spark_response = call_spark_lite_api(prompt)
            if spark_response:
                analysis_result = parse_ai_response(spark_response)
                if analysis_result:
                    logger.info("Spark Lite API分析成功")
                    return analysis_result
        except Exception as spark_error:
            logger.error(f"Spark Lite API调用失败: {spark_error}")
        
        # 如果Spark Lite API失败，使用备用分析
        logger.warning("Spark Lite API调用失败，使用备用分析")
        return fallback_analysis(resume_text, industry)
            
    except Exception as e:
        logger.error(f"AI分析过程中出现错误: {str(e)}")
        return fallback_analysis(resume_text, industry)

def parse_ai_response(ai_response):
    """
    解析AI响应，提取JSON格式的分析结果
    """
    try:
        # 尝试解析JSON响应
        # 有时AI会返回带有额外文本的响应，需要提取JSON部分
        import re
        json_match = re.search(r'\{.*\}', ai_response, re.DOTALL)
        if json_match:
            json_str = json_match.group()
            analysis_result = json.loads(json_str)
            
            # 验证返回的数据结构
            required_keys = ['keywords', 'strengths', 'weaknesses', 'suggestions']
            if all(key in analysis_result for key in required_keys):
                return analysis_result
            else:
                logger.warning("AI返回的JSON缺少必要字段")
                return None
        else:
            logger.warning("无法从AI响应中提取JSON")
            return None
            
    except json.JSONDecodeError as e:
        logger.error(f"解析AI响应JSON失败: {str(e)}")
        return None
    except Exception as e:
        logger.error(f"解析AI响应时出现错误: {str(e)}")
        return None

def fallback_analysis(resume_text, industry):
    """
    备用分析方法（当AI API不可用时使用）
    """
    # 行业相关的技能关键词映射
    industry_keywords = {
        'technology': ["Java", "Python", "JavaScript", "React", "Vue", "Spring Boot", 
                      "MySQL", "Redis", "Docker", "Kubernetes", "Git", "Linux",
                      "HTML", "CSS", "Node.js", "MongoDB", "PostgreSQL", "AWS", "微服务", "前端", "后端"],
        'finance': ["金融", "银行", "投资", "风控", "量化", "交易", "资产管理", "保险", "证券", "基金", "财务分析", "审计"],
        'education': ["教育", "培训", "教学", "课程设计", "学习管理", "在线教育", "教育技术", "教师", "培训师"],
        'healthcare': ["医疗", "健康", "护理", "医学", "药学", "生物技术", "医疗器械", "临床", "诊断", "治疗"],
        'manufacturing': ["制造", "生产", "工艺", "质量管理", "供应链", "精益生产", "自动化", "机械", "工程", "制造工艺", "生产管理"],
        'retail': ["零售", "电商", "销售", "市场营销", "客户服务", "供应链管理", "商品管理", "渠道管理"],
        'consulting': ["咨询", "管理", "战略", "项目管理", "业务分析", "流程优化", "变革管理", "客户关系"],
        'media': ["媒体", "广告", "营销", "创意", "设计", "内容创作", "品牌管理", "数字营销", "社交媒体"],
        'real_estate': ["房地产", "物业管理", "建筑", "工程管理", "投资", "开发", "销售", "租赁"],
        'logistics': ["物流", "运输", "仓储", "供应链", "配送", "货运", "快递", "库存管理"],
        'government': ["公务员", "政府", "公共管理", "政策分析", "行政管理", "法律", "合规", "公共服务"],
        'other': ["管理", "沟通", "团队合作", "项目管理", "分析能力", "解决问题", "创新思维"]
    }
    
    # 获取行业相关关键词，如果是自定义行业，使用通用关键词
    if industry in industry_keywords:
        relevant_keywords = industry_keywords[industry]
    else:
        # 对于自定义行业，使用通用技能关键词
        relevant_keywords = industry_keywords['other'] + ["专业技能", "工作经验", "项目经验", "技术能力", "管理能力"]
    
    # 关键词提取逻辑
    keywords = []
    for keyword in relevant_keywords:
        if keyword.lower() in resume_text.lower() or keyword in resume_text:
            keywords.append(keyword)
    
    # 基于行业和简历内容生成分析
    return generate_industry_specific_analysis(resume_text, industry, keywords)

def generate_industry_specific_analysis(resume_text, industry, keywords):
    """
    基于行业生成具体的分析内容（备用方法）
    """
    # 检查专业背景与目标行业的匹配度
    mismatch_indicators = {
        'manufacturing': ['烹饪', '厨师', '餐饮', '美食', '烘焙', '西点'],
        'technology': ['烹饪', '厨师', '餐饮', '美食', '烘焙', '西点', '文学', '艺术'],
        'finance': ['烹饪', '厨师', '餐饮', '美食', '烘焙', '西点', '艺术', '设计']
    }
    
    # 检查是否存在专业不匹配（仅对预定义行业进行检查）
    mismatched_background = False
    if industry in mismatch_indicators:
        for indicator in mismatch_indicators[industry]:
            if indicator in resume_text:
                mismatched_background = True
                break
    
    # 行业特定的分析模板
    if mismatched_background and industry == 'manufacturing':
        return {
            "keywords": keywords[:5] if keywords else ["基础技能"],
            "strengths": "具备一定的实践操作经验和细致的工作态度",
            "weaknesses": "专业背景与制造业不匹配，缺乏制造工艺、生产管理、质量控制等核心技能和经验",
            "suggestions": "建议学习制造业相关知识，如生产工艺、质量管理体系、精益生产等，考虑通过培训或实习获得制造业经验"
        }
    
    # 对于自定义行业，生成通用但针对性的分析
    keyword_count = len(keywords)
    
    if keyword_count >= 5:
        strengths = f"具备{', '.join(keywords[:3])}等相关技能，在{industry}领域有一定的技术基础"
    elif keyword_count >= 3:
        strengths = f"掌握{len(keywords)}项相关技能，对{industry}行业有基础了解"
    else:
        strengths = f"具备基础的专业技能，有学习{industry}行业知识的潜力"
    
    if len(resume_text) < 200:
        weaknesses = f"简历内容较为简单，建议补充更多与{industry}相关的工作经历和项目经验"
    else:
        weaknesses = f"建议补充更多{industry}行业的实战经验和具体成果数据"
    
    suggestions = f"建议深入学习{industry}行业的专业知识和技能，关注行业发展趋势，积累相关项目经验"
    
    return {
        "keywords": keywords[:8],
        "strengths": strengths,
        "weaknesses": weaknesses,
        "suggestions": suggestions
    }

def calculate_match_score(analysis_result, industry):
    """
    根据分析结果计算匹配度分数
    """
    try:
        keywords = analysis_result.get('keywords', [])
        strengths = analysis_result.get('strengths', '')
        weaknesses = analysis_result.get('weaknesses', '')
        
        # 基础分数
        base_score = 50
        
        # 关键词匹配加分
        keyword_score = min(len(keywords) * 5, 30)
        
        # 根据优势和劣势内容调整分数
        if '不匹配' in weaknesses or '缺乏' in weaknesses:
            mismatch_penalty = -20
        else:
            mismatch_penalty = 0
            
        if '扎实' in strengths or '丰富' in strengths or '优秀' in strengths:
            strength_bonus = 10
        else:
            strength_bonus = 0
            
        final_score = base_score + keyword_score + mismatch_penalty + strength_bonus
        
        # 确保分数在0-100范围内
        return max(0, min(100, final_score))
        
    except Exception as e:
        logger.error(f"计算匹配度时出现错误: {str(e)}")
        return 60  # 默认分数

@app.route('/analyze', methods=['POST'])
@app.route('/resume/analyze', methods=['POST'])
def analyze_resume():
    try:
        data = request.get_json()
        
        # 兼容两种字段名称格式
        resume_text = data.get('resumeText') or data.get('resume_text')
        
        if not data or not resume_text:
            error_response = make_response(jsonify({
                'success': False,
                'error': '请提供简历文本'
            }))
            error_response.headers['Content-Type'] = 'application/json; charset=utf-8'
            return error_response, 400
        industry = data.get('industry', 'technology')
        
        logger.info(f"收到简历分析请求，内容长度: {len(resume_text)}, 目标行业: {industry}")
        
        # 调用AI分析
        analysis_result = analyze_resume_with_ai(resume_text, industry)
        
        # 计算匹配度
        match_score = calculate_match_score(analysis_result, industry)
        
        response_data = {
            'success': True,
            'matchScore': match_score,
            'keywords': analysis_result.get('keywords', []),
            'strengths': analysis_result.get('strengths', ''),
            'weaknesses': analysis_result.get('weaknesses', ''),
            'suggestions': analysis_result.get('suggestions', ''),
            'message': '分析完成'
        }
        
        logger.info("简历分析完成")
        
        # 确保返回UTF-8编码的JSON
        response = make_response(jsonify(response_data))
        response.headers['Content-Type'] = 'application/json; charset=utf-8'
        return response
        
    except Exception as e:
        logger.error(f"分析过程中出现错误: {str(e)}")
        error_response = make_response(jsonify({
            'success': False,
            'error': '分析失败，请稍后重试'
        }))
        error_response.headers['Content-Type'] = 'application/json; charset=utf-8'
        return error_response, 500

@app.route('/health', methods=['GET'])
def health_check():
    """健康检查接口"""
    return jsonify({
        "status": "healthy",
        "service": "SmartResume-AI Server",
        "version": "1.0.0"
    })

@app.route('/resume/health', methods=['GET'])
def resume_health_check():
    """简历服务健康检查接口"""
    return jsonify({
        "status": "healthy",
        "service": "SmartResume-AI Resume Service",
        "version": "1.0.0",
        "endpoints": {
            "analyze": "/analyze",
            "health": "/health",
            "resume_health": "/resume/health"
        }
    })

if __name__ == '__main__':
    logger.info("启动SmartResume-AI服务...")
    logger.info("服务地址: http://localhost:5005")
    logger.info("分析接口: POST /analyze")
    logger.info("健康检查: GET /health")
    
    app.run(host='0.0.0.0', port=5005, debug=True)